package com.lalilu.lread

import android.content.Context
import android.net.Uri
import android.webkit.WebView
import com.lalilu.lread.base.BaseEpubShower
import com.lalilu.lread.entity.LBook
import com.lalilu.lread.utils.StringUtil
import nl.siegmann.epublib.domain.Book
import nl.siegmann.epublib.epub.EpubReader
import org.jsoup.Jsoup
import org.jsoup.nodes.Node
import java.util.logging.Logger

class EpubShower(context: Context) : BaseEpubShower<WebView, LBook> {
    private val logger = Logger.getLogger(this.javaClass.name)
    private val globalConfig = GlobalConfig.getInstance(context)
    private val contentResolver = context.contentResolver
    private val epubReader = EpubReader()
    override var source: LBook? = null

    private var data: Book? = null
    private var document: String? = null

    private var baseUrl = "file://${globalConfig.cachePath}/"
    private var mimeType = "text/html"
    private var encoding = "utf-8"

    /**
     * 加载书籍数据至 data 变量中，以供后续使用
     * @param item 传入LBook实体，进行书籍数据的加载
     * @return 返回 EpubShower 自身以供链式调用
     */
    override fun load(item: LBook): BaseEpubShower<WebView, LBook> {
        source = item

        val inputStream = contentResolver?.openInputStream(Uri.parse(item.uriString))
        data = epubReader.readEpub(inputStream)
        inputStream?.close()
        return this
    }


    /**
     * 根据指定页码，将指定页的文本数据加载进 document 变量中
     * @param pageNum 传入页码
     * @return 返回 EpubShower 自身以供链式调用
     */
    override fun select(pageNum: Int): BaseEpubShower<WebView, LBook> {
        selectDocument(pageNum)
        return this
    }


    /**
     * 根据指定页码，获取指定页的文本数据
     * @param pageNum 传入页码
     * @return 返回经过路径解析变换处理过后的页文本数据
     */
    override fun selectDocument(pageNum: Int): String? {
        return try {
            val temp = data!!.contents[pageNum].data
            document = parsePath(StringUtil.bytesToString(temp))
            document
        } catch (e: Exception) {
            logger.warning("[selectDocument exception]: ${e.message}")
            null
        }
    }

    /**
     * 将加载好的页文本数据加载进指定 webView 中进行展示
     * @param target 指定目标 WebView
     */
    override fun showAt(target: WebView) {
        if (document == null) return

        target.settings.allowFileAccess = true
        target.settings.allowContentAccess = true
        WebView.setWebContentsDebuggingEnabled(true)
        target.loadDataWithBaseURL(baseUrl, document!!, mimeType, encoding, null)
    }

    /**
     * 将指定元素的路径转化为处于根目录的路径
     * @param data 原始页文本数据
     * @return 路径解析处理过后的页文本数据
     */
    override fun parsePath(data: String): String {
        val document = Jsoup.parse(data)
        document.head().appendElement("style").appendText(globalConfig.customizeCss)
        for (img in document.select("img")) parseToAbsolutePath(img, "src")
        for (link in document.select("link[type='text/css']")) parseToAbsolutePath(link, "href")
        return document.toString()
    }

    private fun parseToAbsolutePath(node: Node, attr: String) {
        if (source == null || data == null) return

        val path = node.attr(attr)
        var result = StringUtil.getFileNameFromPath(path)
        val ext = StringUtil.getExtFromText(result)

        if (listOf("jpg", "png", "jpeg").contains(ext)) {
            result = StringUtil.changeExtFromText(result, "webp")
        }
        node.attr(attr, "./${globalConfig.tempPrefix}${source!!.id}_$result")
    }


    companion object {
        @Volatile
        private var instance: EpubShower? = null

        fun getInstance(context: Context?): EpubShower {
            instance ?: synchronized(EpubShower::class.java) {
                instance = instance ?: EpubShower(context!!)
            }
            return instance!!
        }
    }


}